﻿using System;

namespace LxCFD
{
    public class EquationBase : MatrixBase
    {
        public TransientScalar TransData;

        public virtual void Set_x_Bound(int taskIndex)
        {
            throw new NotImplementedException();
        }
        public virtual void SetAb_Step1(int taskIndex)
        {
            throw new NotImplementedException();
        }
        public virtual void SetAb_Step2(int taskIndex)
        {
            throw new NotImplementedException();
        }
        public virtual void Update_x_Bound(int taskIndex)
        {
            throw new NotImplementedException();
        }
        public void CopyFromOldEquation(EquationBase oldEquation)
        {
            if (oldEquation == null) return;
            this.x = oldEquation.x;
            this.IsInitialized = oldEquation.IsInitialized;
            if (oldEquation.TransData == null) return;
            this.TransData = oldEquation.TransData;
        }
        public void SetZone_TransTerm(bool isEnable, Value1Base<double> Trans, Value1Base<double> density)//isEnable其实没必要传，主要是提醒，在不启用时Trans和density只传入null即可
        {
            if (isEnable)
            {
                if (TransData == null)
                {
                    TransData = new TransientScalar();
                    TransData.CheckCreate(this);
                }
                TransData.SetTransient(Trans, density);
            }
            else
            {
                TransData = null;
            }
        }
        public class TransientScalar : TransientDataBase
        {
            public Value1Base<double> Trans;
            public Value1Base<double> Density;

            public double[] RhoVolPhi_o;
            public double[] RhoVolPhi_oo;

            protected EquationBase Matrix;
            protected double[] x;
            protected double[] b;
            protected double[] ADiag;
            protected FvCell[] Cells;
            public void CheckCreate(EquationBase Matrix)
            {
                this.Matrix = Matrix;
                LxTool.CheckCreateArray(ref RhoVolPhi_o, Matrix.InnerIndex.CellIDs.GetCount());
                LxTool.CheckCreateArray(ref RhoVolPhi_oo, Matrix.InnerIndex.CellIDs.GetCount());
                //TransientDataState = TransientDataStates.None;
            }
            public void SetTransient(Value1Base<double> Trans, Value1Base<double> density)
            {
                this.x = Matrix.x;
                this.ADiag = Matrix.ADiag;
                this.b = Matrix.b;
                this.Cells = Matrix.Cells;

                this.Trans = Trans;
                this.Density = density;
            }
            public override void SaveOldValue(int taskIndex)
            {
                Matrix.InnerIndex.CellIDs.GetSeg(out int i1, out int endp1, taskIndex);
                for (; i1 < endp1; i1++)
                {
                    RhoVolPhi_o[i1] = Trans.GetCellValue(i1) * Density.GetCellValue(i1) * Cells[i1].Volumn * x[i1];
                }
            }
            public override void PrepareToSave()
            {
                LxTool.Exchange(ref RhoVolPhi_o, ref RhoVolPhi_oo);
                switch (TransientDataState)
                {
                    case TransientDataStates.None: TransientDataState = TransientDataStates.Only_o; break;
                    case TransientDataStates.Only_o: TransientDataState = TransientDataStates.Both_o_oo; break;
                    default: break;
                }
            }
            public void SetAb_ImplicitTrans(int taskIndex)
            {
                if (IsSecondOrder && TransientDataState == TransientDataStates.Both_o_oo)
                {
                    Matrix.InnerIndex.CellIDs.GetSeg(out int i1, out int endp1, taskIndex);
                    for (; i1 < endp1; i1++)
                    {
                        b[i1] -= Factor_PhiO_2ndOrder * RhoVolPhi_o[i1] + Factor_PhiOO_2ndOrder * RhoVolPhi_oo[i1];
                        ADiag[i1] += Factor_Phi_2ndOrder * Trans.GetCellValue(i1) * Density.GetCellValue(i1) * Cells[i1].Volumn;
                    }
                }
                else
                {
                    Matrix.InnerIndex.CellIDs.GetSeg(out int i1, out int endp1, taskIndex);
                    for (; i1 < endp1; i1++)
                    {
                        b[i1] += Factor_Phi_2ndOrder * RhoVolPhi_o[i1];
                        ADiag[i1] += Factor_Phi_2ndOrder * Trans.GetCellValue(i1) * Density.GetCellValue(i1) * Cells[i1].Volumn;
                    }
                }
            }
            public void SetAb_ExplicitTrans(int taskIndex)
            {
                if (IsSecondOrder && TransientDataState == TransientDataStates.Both_o_oo)
                {
                    Matrix.InnerIndex.CellIDs.GetSeg(out int i1, out int endp1, taskIndex);
                    for (; i1 < endp1; i1++)
                    {
                        b[i1] += -ADiag[i1] * x[i1] - Factor_PhiO_2ndOrder * RhoVolPhi_o[i1] - Factor_PhiOO_2ndOrder * RhoVolPhi_oo[i1];//-calALUProductValue(ref cells[i1], x),显示求解的时候会做，这里不做
                        ADiag[i1] = Factor_Phi_2ndOrder * Trans.GetCellValue(i1) * Density.GetCellValue(i1) * Cells[i1].Volumn;
                    }
                }
                else
                {
                    Matrix.InnerIndex.CellIDs.GetSeg(out int i1, out int endp1, taskIndex);
                    for (; i1 < endp1; i1++)
                    {
                        b[i1] += -ADiag[i1] * x[i1] + Factor_Phi_2ndOrder * RhoVolPhi_o[i1]; //-calALUProductValue(ref cells[i1], x),显示求解的时候会做，这里不做
                        ADiag[i1] = Factor_Phi_2ndOrder * Trans.GetCellValue(i1) * Density.GetCellValue(i1) * Cells[i1].Volumn;//beforePhiO和beforePhi互为相反数，因此不用获取
                    }
                }
            }
            public override void Initialize()
            {
                MultiThreads.RunCalTasks(SaveOldValue);
            }
        }
    }
}
//if (AppRes.computeCenter.isTransient)
//{
//    if (transientRecorder == null)
//    {
//        transientRecorder = new TransientDataRecorder();
//        transientRecorder.Create(this);
//    }

//}
//else
//{
//    transientRecorder = null;
//}